home *** CD-ROM | disk | FTP | other *** search
/ Workbench Design / WB Collection.iso / workbench werkzeuge / guis für programme / devicelock / txt / devicelock.mod < prev    next >
Text File  |  1996-04-07  |  18KB  |  564 lines

  1. (*---------------------------------------------------------------------------
  2.  :Program.    DeviceLock.mod
  3.  :Author.     Thomas Wagner
  4.  :Address.    Mühlenweg 7, 90602 Pyrbaum, Germany
  5.  :Address.    E-Mail: tom@oberon.nbg.sub.org
  6.  :Copyright.  © 1994 by Thomas Wagner [tom], see DeviceLock.guide
  7.  :Language.   Oberon
  8.  :Translator. Amiga Oberon Compiler V3.11d
  9.  :Import.     HotKey.mod         V2.0 Thomas Igracki, [tom]  (on this disk)
  10.  :Import.     MoreIntuition.mod  V1.3 [mick]                 (Amok 78)
  11.  :Import.     WBReadArgs.mod     V1.0 [hG]                   (Amok 83)
  12.  :Import.     PrintF.mod         V1.4 Volker Rudolph, [hG]   (Amok 82)
  13.  :Contents.   Lock with Intuition-Interface (2.04 or higher ONLY!)
  14. ---------------------------------------------------------------------------*)
  15.  
  16. MODULE DeviceLock;
  17.  
  18. (*-------------------------------------------------------------------------*)
  19.  
  20. IMPORT c  := Conversions,
  21.        d  := Dos,
  22.        DLd:= DLdrives,
  23.        DLr:= DLrequester,
  24.        DLs:= DLstrings,
  25.        DLp:= DLprefs,
  26.        e  := Exec,
  27.        g  := Graphics,
  28.        gt := GadTools,
  29.        hot:= HotKey,
  30.        I  := Intuition,
  31.        MI := MoreIntuition,
  32.        ol := OberonLib,
  33.        s  := Strings,
  34.        sys:= SYSTEM,
  35.        t  := Timer,
  36.        u  := Utility;
  37.  
  38. (*-------------------------------------------------------------------------*)
  39.  
  40. CONST
  41.  
  42.   comName  *= "DeviceLock\o$VER: DeviceLock 1.2 (17.3.94)";
  43.   comTitle *= "DeviceLock, 1.2 © 1994 [tom]";
  44.   comDescr *= "Intuition-Interface for CLI-Lock";
  45.  
  46.   scrtitle = "DeviceLock, 1.2 - © 1994 by Thomas Wagner. All Rights reserved.";
  47.  
  48.   about    = "DeviceLock 1.2\n\n"
  49.              "© 1994 by Thomas Wagner, Pyrbaum [tom].\n"
  50.               "%s";
  51.  
  52.   topadd = 5 ;
  53.  
  54.   checkscal = 2421;
  55.  
  56. (*-------------------------------------------------------------------------*)
  57.  
  58. TYPE
  59.  
  60.     NewMenus = ARRAY 10 OF gt.NewMenu;
  61.  
  62. (*-------------------------------------------------------------------------*)
  63.  
  64. CONST
  65.  
  66.   menuLock     = 1;
  67.   menuUnlock   = 2;
  68.   menuNorm     = 3;
  69.   menuAbout    = 4;
  70.   menuHide     = 5;
  71.   menuQuit     = 6;
  72.  
  73.  
  74.   myNewMenuConst = NewMenus(
  75.     gt.title, NIL,         NIL,          {}, LONGSET{}, NIL,
  76.     gt.item , NIL,         sys.ADR("L"), {}, LONGSET{}, menuLock,
  77.     gt.item , NIL,         sys.ADR("U"), {}, LONGSET{}, menuUnlock,
  78.     gt.item , NIL,         sys.ADR("U"), {}, LONGSET{}, menuNorm,
  79.     gt.item , gt.barLabel, NIL,          {}, LONGSET{}, NIL,
  80.     gt.item , NIL,         sys.ADR("?"), {}, LONGSET{}, menuAbout,
  81.     gt.item , gt.barLabel, NIL,          {}, LONGSET{}, NIL,
  82.     gt.item , NIL,         sys.ADR("H"), {}, LONGSET{}, menuHide,
  83.     gt.item , NIL,         sys.ADR("Q"), {}, LONGSET{}, menuQuit,
  84.     gt.end  , NIL,         NIL,          {}, LONGSET{}, NIL);
  85. (*-------------------------------------------------------------------------*)
  86.  
  87. VAR
  88.   font          : g.TextFontPtr;
  89.   ng            : gt.NewGadget;
  90.   glist         : I.GadgetPtr;
  91.   gad           : I.GadgetPtr;
  92.   vi            : e.APTR;
  93.   terminated    : BOOLEAN;
  94.   imsg          : I.IntuiMessagePtr;
  95.   imsgClass     : LONGSET;
  96.   imsgCode      : INTEGER;
  97.   count         : INTEGER;
  98.   TimerPort     : e.MsgPortPtr;
  99.   TimeReq       : t.TimeRequestPtr;
  100.   OpenDev       : SHORTINT;
  101.   signals       : LONGSET;
  102.   allock        : BOOLEAN;
  103.   allunlock     : BOOLEAN;
  104.   quickquit     : BOOLEAN;
  105.   keepquit      : BOOLEAN;
  106.   gheight       : INTEGER;
  107.   wheight       : INTEGER;
  108.   wwidth        : INTEGER;
  109.   windowopen    : BOOLEAN;
  110.   HotSig        : SHORTINT;
  111.   HotType    : LONGSET;
  112.   HotID         : LONGINT;
  113.   closewin      : BOOLEAN;
  114.   myNewMenu     : NewMenus;
  115.   menu          : I.MenuPtr;
  116.   topborder     : INTEGER;
  117.   zoom          : ARRAY 4 OF INTEGER;
  118.   force         : BOOLEAN;
  119.  
  120.  
  121. (*------ Append one Gadget to Gadget-List ---------------------------------*)
  122.  
  123. PROCEDURE * MakeGad(VAR n: DLp.driveT);
  124. BEGIN
  125.   ng.topEdge := topborder + topadd + 2 + (count)*gheight;
  126.   ng.gadgetText := sys.ADR(n.PrintName);
  127.   ng.gadgetID := count;
  128.   gad := gt.CreateGadget(gt.checkBoxKind, gad, ng,
  129.                          I.gaDisabled, sys.VAL(SHORTINT,n.disabled),
  130.                          gt.cbChecked, sys.VAL(SHORTINT,n.locked),
  131.                          gt.cbScaled, I.LTRUE,
  132.                          u.done);
  133.   n.GadPtr:=gad;
  134. END MakeGad;
  135.  
  136.  
  137. (*------ Prepare and Send IO ----------------------------------------------*)
  138.  
  139. PROCEDURE psIO();
  140. BEGIN
  141.   TimeReq.time.secs  := DLp.Prefs.CheckTime;
  142.   TimeReq.time.micro := 0;
  143.   e.SendIO(TimeReq);
  144. END psIO;
  145.  
  146.  
  147. (*------ Do something on response to a pressed Gadget ---------------------*)
  148.  
  149. PROCEDURE HandleGadgetEvent(gad: I.GadgetPtr; code: INTEGER);
  150. BEGIN
  151.   IF gad.gadgetID =  0 THEN
  152.     DLd.LockAll(FALSE);
  153.   ELSE
  154.     IF gad.gadgetID<=DLp.Prefs.DriveNum THEN
  155.       IF I.selected IN gad.flags THEN
  156.         DLd.LckOne(DLp.drive[gad.gadgetID-1])
  157.       ELSE
  158.         DLd.UnLckOne(DLp.drive[gad.gadgetID-1])
  159.       END;
  160.     END;
  161.     force := FALSE;
  162.   END;
  163. END HandleGadgetEvent;
  164.  
  165. (*------ Response to Menu-select ------------------------------------------*)
  166.  
  167. PROCEDURE HandleMenuEvent(code: INTEGER);
  168.  
  169. VAR
  170.   item: I.MenuItemPtr;
  171.  
  172. BEGIN
  173.   WHILE (code # I.menuNull) AND ~ terminated DO
  174.     item := I.ItemAddress(menu^, code);
  175.     CASE sys.VAL(LONGINT,gt.MenuItemUserData(item)) OF
  176.       menuLock   : DLd.LockAll(FALSE); |
  177.       menuUnlock : DLd.UnlockAll(FALSE); |
  178.       menuNorm   : DLd.NormAll(); |
  179.       menuAbout  : DLr.RequestNotify(DLs.GetString(DLs.MsgAbout),
  180.                                    sys.ADR(about),
  181.                                    DLs.GetString(DLs.MsgAllRightsReserved)); |
  182.       menuHide   : closewin   := TRUE; |
  183.       menuQuit   : terminated := TRUE; quickquit := FALSE |
  184.     ELSE END;
  185.  
  186.     code := item.nextSelect;
  187.  
  188.   END;
  189.  
  190. END HandleMenuEvent;
  191.  
  192. (*------ Lock all window-specific resources and open window ---------------*)
  193.  
  194. PROCEDURE OpenWindow(hijackfront: BOOLEAN);
  195. VAR    twidth  : INTEGER;
  196.        mysc    : I.ScreenPtr;
  197.        gadwidth: LONGINT;
  198.  
  199.   (*------ Starts Gadget-List and calls MakeGadget --------------------------*)
  200.  
  201.   PROCEDURE CreateAllGadgets(VAR glist: I.GadgetPtr;
  202.                                  vi: e.APTR;
  203.                                  topborder: INTEGER;
  204.                                  mysc: I.ScreenPtr): BOOLEAN;
  205.   BEGIN
  206.     gad := gt.CreateContext(glist);
  207.     ng.textAttr := mysc.font;
  208.     ng.leftEdge := 8;
  209.     ng.topEdge := topadd + topborder;
  210.     ng.width := wwidth-15;
  211.     ng.height := gheight + 2;
  212.     ng.gadgetText := DLs.GetString(DLs.GadLockAll);
  213.     ng.flags := LONGSET{};
  214.     ng.gadgetID := 0;
  215.     ng.visualInfo := vi;
  216.     gad := gt.CreateGadget(gt.buttonKind, gad, ng, u.done);
  217.  
  218.     ng.flags := LONGSET{gt.placeTextRight};
  219.     ng.height := gheight;
  220.     ng.width := SHORT(gadwidth);
  221.     FOR count := 1 TO DLp.Prefs.DriveNum DO
  222.       MakeGad(DLp.drive[count-1]);
  223.     END;
  224.  
  225.     RETURN gad#NIL;
  226.  
  227.   END CreateAllGadgets;
  228.  
  229.   (*---- Check and FailOut if FALSE   +  Unlock PubScreen! ----------------*)
  230.   PROCEDURE CheckAndFail(test: BOOLEAN; error: ARRAY OF CHAR); (* $CopyArrays- *)
  231.   BEGIN
  232.     IF ~test THEN
  233.       (* Save to call with mysc=NIL ! *) I.UnlockPubScreen(NIL,mysc);
  234.       DLr.FailOut(error);
  235.     END;
  236.   END CheckAndFail;
  237.  
  238.   (*---- Swaps two INTEGER's ----------------------------------------------*)
  239.   PROCEDURE SwapInt(VAR x,y: INTEGER);
  240.   VAR s: INTEGER;
  241.   BEGIN
  242.     s := x;
  243.     x := y;
  244.     y := s;
  245.   END SwapInt;
  246.  
  247.   (*---- Max of two INTEGER's ---------------------------------------------*)
  248.   PROCEDURE Max(x,y: INTEGER):INTEGER;
  249.   BEGIN
  250.   IF x > y THEN RETURN(x) ELSE RETURN(y) END;
  251.   END Max;
  252.  
  253.   (*---- Min of two INTEGER's ---------------------------------------------*)
  254.   PROCEDURE Min(x,y: INTEGER):INTEGER;
  255.   BEGIN
  256.   IF x < y THEN RETURN(x) ELSE RETURN(y) END;
  257.   END Min;
  258.  
  259.  
  260. BEGIN
  261.   IF hijackfront THEN
  262.     DLp.Buffer1 := "\o";
  263.     mysc := MI.LockFrontPubScr(DLp.Buffer1);
  264.   ELSE
  265.     mysc := I.LockPubScreen(DLp.Prefs.PubScreen);
  266.   END;
  267.   IF mysc=NIL THEN mysc := I.LockPubScreen(NIL) END;
  268.   CheckAndFail(mysc#NIL,"LockPubScreen()");
  269.  
  270.   font := g.OpenFont(mysc.font^);
  271.   CheckAndFail(font#NIL,"OpenFont()");
  272.  
  273.   zoom[0] := DLp.Prefs.LeftEdgeZoomed;
  274.   zoom[1] := DLp.Prefs.TopEdgeZoomed;
  275.  
  276.   gheight := mysc.font.ySize;
  277.   IF gheight < 11 THEN gheight := 11 END;
  278.  
  279.   wwidth := g.TextLength(sys.ADR(mysc.rastPort),
  280.                          DLs.GetString(DLs.GadLockAll)^,
  281.                          s.Length(DLs.GetString(DLs.GadLockAll)^))+40;
  282.   IF DLp.OSrelease3 THEN
  283.     gadwidth := gheight;
  284.     gadwidth := gadwidth * checkscal DIV 1024; (* Operation LONGINT *)
  285.   ELSE
  286.     gadwidth := 26;
  287.   END;
  288.   FOR count := 0 TO DLp.Prefs.DriveNum-1 DO
  289.     twidth := g.TextLength(sys.ADR(mysc.rastPort),
  290.                            DLp.drive[count].PrintName,
  291.                            s.Length(DLp.drive[count].PrintName))
  292.                            + SHORT(gadwidth) + 30  ;
  293.     IF  twidth > wwidth THEN wwidth := twidth END;
  294.   END; (* FOR *)
  295.  
  296.  
  297.   vi := gt.GetVisualInfo(mysc,u.done);
  298.   CheckAndFail(vi#NIL,"GetVisualInfo()");
  299.  
  300.   topborder := mysc.wBorTop + mysc.font.ySize;
  301.  
  302.   menu := gt.CreateMenus(myNewMenu,u.done);
  303.   IF menu=NIL THEN DLr.FailOut("CreateMenus()") END;
  304.   CheckAndFail(gt.LayoutMenus(menu, vi, gt.mnNewLookMenus, I.LTRUE, u.done),"LayoutMenus()");
  305.  
  306.   CheckAndFail(CreateAllGadgets(glist,vi,topborder,mysc),"CreateAllGadgets()");
  307.   wheight:=(DLp.Prefs.DriveNum+1) * gheight + 2 * topadd + topborder + mysc.wBorBottom;
  308.  
  309.   zoom[2] :=   Min(DLd.maxTitles,DLp.Prefs.DriveNum) 
  310.              * Max(g.TextLength(sys.ADR(mysc.rastPort),"-",1),
  311.                    g.TextLength(sys.ADR(mysc.rastPort),"+",1))
  312.              + 85;
  313.  
  314.   zoom[3] := topborder + 1;
  315.  
  316.   IF DLp.Prefs.OpenZoomed THEN 
  317.     SwapInt(zoom[2],wwidth);
  318.     SwapInt(zoom[3],wheight);
  319.   END;
  320.  
  321.   DLd.mywin := I.OpenWindowTagsA(NIL,
  322.                             I.waLeft, DLp.Prefs.LeftEdge,
  323.                             I.waTop, DLp.Prefs.TopEdge,
  324.                             I.waHeight,wheight,
  325.                             I.waWidth,wwidth,
  326.                             I.waScreenTitle, sys.ADR(scrtitle),
  327.                             I.waPubScreen,  mysc,
  328.                             I.waGadgets, glist,
  329.                             I.waZoom, sys.ADR(zoom),
  330.                             I.waIDCMP, LONGSET{I.mouseButtons,
  331.                                                I.refreshWindow,
  332.                                                I.gadgetUp,
  333.                                                I.menuPick,
  334.                                                I.activeWindow,
  335.                                                I.inactiveWindow,
  336.                                                I.closeWindow,
  337.                                                I.diskInserted,
  338.                                                I.diskRemoved},
  339.                             I.waFlags, LONGSET{I.windowDrag,
  340.                                                I.windowDepth,
  341.                                                I.windowClose,
  342.                                                I.newLookMenus},
  343.                             u.done);
  344.   CheckAndFail(DLd.mywin#NIL,"OpenWindow()");
  345.  
  346.   (* Window is open and all important screen-datas are scanned, so
  347.      it isn't necessary to keep the lock on the PubScreen *)
  348.   I.UnlockPubScreen(NIL,mysc);
  349.   DLr.yourwin := DLd.mywin;
  350.   gt.RefreshWindow(DLd.mywin, NIL);
  351.   IF I.SetMenuStrip(DLd.mywin, menu^) THEN END;
  352.  
  353.   windowopen := TRUE;
  354.   DLd.CheckDrives(TRUE); (* force refresh *)
  355.  
  356. END OpenWindow;
  357.  
  358.  
  359. (*------ Close window and unlock all window-specific resources ------------*)
  360.  
  361. PROCEDURE CloseWindow();
  362. BEGIN
  363.   windowopen := FALSE;
  364.   DLr.yourwin := NIL;
  365.   IF e.CheckIO(TimeReq)= NIL THEN e.AbortIO(TimeReq)                        END;
  366.   IF DLd.mywin             # NIL THEN 
  367.     I.ClearMenuStrip(DLd.mywin);
  368.     I.CloseWindow(DLd.mywin); DLd.mywin := NIL;
  369.   END;
  370.   (* Save to call with NIL ! *)   gt.FreeMenus(menu); menu := NIL;
  371.   (* Save to call with NIL ! *)   gt.FreeVisualInfo(vi); vi := NIL;
  372.   (* Save to call with NIL ! *)   gt.FreeGadgets(glist); glist := NIL;
  373.   IF font              # NIL THEN g.CloseFont(font); font := NIL            END;
  374.   IF e.WaitIO(TimeReq) = 0   THEN                                           END;
  375. END CloseWindow;
  376.  
  377.  
  378. (***************************************************************************
  379.          M A I N
  380.  ***************************************************************************)
  381.  
  382. BEGIN
  383.  
  384. (*------ Open all necessary resources -------------------------------------*)
  385.  
  386.   IF (I.int.libNode.version<37) THEN HALT(20) END;
  387.  
  388.   OpenDev := topadd; (* DUMMY *)
  389.  
  390.   DLp.ReadArgs;
  391.  
  392.   terminated := FALSE;
  393.   keepquit := FALSE;
  394.  
  395.   HotSig := hot.InitX(comName,comTitle,comDescr,{hot.notify},TRUE,SHORT(SHORT(DLp.Argv.pri^)));
  396.   IF HotSig < 0 THEN HALT(0) END;
  397.  
  398.   myNewMenu := myNewMenuConst;
  399.  
  400.   DLs.FillMenu(myNewMenu);
  401.  
  402.   TimerPort := e.CreateMsgPort();
  403.   IF TimerPort = NIL THEN DLr.FailOut("CreateMsgPort()") END;
  404.  
  405.   TimeReq := e.CreateIORequest(TimerPort,SIZE(t.TimeRequest));
  406.   IF TimeReq = NIL THEN DLr.FailOut("CreateIORequest()") END;
  407.  
  408.   OpenDev := e.OpenDevice(t.timerName,t.vBlank,TimeReq,LONGSET{});
  409.   IF OpenDev # 0 THEN
  410.     DLr.FailOut("OpenDevice(Timer)")
  411.   END;
  412.  
  413.   TimeReq.node.command := t.addRequest;
  414.   TimeReq.node.error := 0;
  415.  
  416.   psIO;
  417.   DLp.ReadPrefs;
  418.   DLd.CheckDrivesInit;
  419.   IF DLp.Prefs.OpenWindow THEN OpenWindow(FALSE) END;
  420.   hot.Activate(TRUE);
  421.  
  422.   DLp.FreeArgs; (* everything checked, no longer needed *)
  423.  
  424. (*------ Waiting for Messages (User, Timer) -------------------------------*)
  425.  
  426. WHILE ~ terminated DO
  427.  
  428.   WHILE ~ terminated DO
  429.  
  430.   IF windowopen THEN
  431.     IF e.CheckIO(TimeReq)#NIL THEN
  432.       psIO;
  433.     END;
  434.     signals := e.Wait (LONGSET{DLd.mywin.userPort.sigBit,TimerPort.sigBit,HotSig,d.ctrlC});
  435.   ELSE
  436.     signals := e.Wait (LONGSET{TimerPort.sigBit,HotSig,d.ctrlC});
  437.   END;
  438.  
  439.     IF windowopen AND (DLd.mywin.userPort.sigBit IN signals) THEN
  440.       LOOP
  441.         imsg := gt.GetIMsg(DLd.mywin.userPort);
  442.         IF imsg=NIL THEN EXIT END;
  443.         imsgClass := imsg.class;
  444.         imsgCode := imsg.code;
  445.         gad := imsg.iAddress;
  446.         gt.ReplyIMsg(imsg);
  447.         force := TRUE;
  448.  
  449.         IF I.activeWindow IN imsgClass THEN
  450.           DLd.winactive := TRUE;
  451.           force := FALSE;
  452.         END;
  453.  
  454.         IF I.inactiveWindow IN imsgClass THEN
  455.           DLd.winactive := FALSE
  456.         END;
  457.  
  458.         IF I.refreshWindow IN imsgClass THEN
  459.           gt.BeginRefresh(DLd.mywin);
  460.           gt.EndRefresh(DLd.mywin, I.LTRUE);
  461.           force := FALSE;
  462.         END;
  463.  
  464.         IF I.gadgetUp IN imsgClass THEN
  465.           HandleGadgetEvent(gad, imsgCode);
  466.         END;
  467.  
  468.         IF I.menuPick IN imsgClass THEN
  469.           HandleMenuEvent(imsgCode);
  470.         END;
  471.  
  472.         IF I.closeWindow IN imsgClass THEN
  473.           closewin := TRUE;
  474.         END; (* IF *)
  475.  
  476.         DLd.CheckDrives(force);
  477.  
  478.       END; (* LOOP *)
  479.     END; (* IF DLd.mywin *)
  480.  
  481.     IF closewin THEN
  482.       closewin := FALSE;
  483.       CloseWindow;
  484.     END;
  485.  
  486.     IF HotSig IN signals THEN
  487.       WHILE hot.GetCMsg(HotType,HotID) DO
  488.         IF hot.hotkey IN HotType THEN
  489.           CASE HotID OF
  490.              DLp.lckallHot    : DLd.LockAll(FALSE);
  491.                                 IF DLp.Prefs.LockAllBeep THEN I.DisplayBeep(NIL) END;
  492.            | DLp.normallHot   : DLd.NormAll();
  493.                                 IF DLp.Prefs.NormAllBeep THEN I.DisplayBeep(NIL) END;
  494.            | DLp.gotofrontHot : IF windowopen THEN CloseWindow END;
  495.                                 OpenWindow(TRUE);
  496.            | DLp.opencloseHot : IF windowopen THEN CloseWindow
  497.                                               ELSE OpenWindow(FALSE)  END;
  498.           ELSE
  499.             IF DLp.Prefs.UnlockBeep THEN I.DisplayBeep(NIL) END;
  500.             DLd.UnLckOne(DLp.drive[HotID-1]);
  501.           END; (* CASE *)
  502.           DLd.CheckDrives(TRUE);
  503.         ELSIF hot.command IN HotType THEN
  504.           CASE HotID OF
  505.             hot.cAppear   : IF windowopen THEN DLd.CheckDrives(TRUE)
  506.                                           ELSE OpenWindow(FALSE)      END;
  507.                             I.WindowToFront(DLd.mywin);
  508.                             I.ScreenToFront(DLd.mywin.wScreen);
  509.                             IF DLd.mywin.height = (topborder + 1)
  510.                               THEN I.ZipWindow(DLd.mywin) END;
  511.            |hot.cDisappear: IF windowopen THEN CloseWindow END;|
  512.            |hot.cKill     : terminated := TRUE; quickquit := TRUE;
  513.            |hot.cUnique   : terminated := TRUE; quickquit := TRUE; keepquit := TRUE;
  514.           ELSE
  515.           END; (* CASE *)
  516.         END; (* IF *)
  517.       END; (* WHILE *)
  518.     END; (* IF *)
  519.  
  520.     IF d.ctrlC IN signals THEN terminated := TRUE; quickquit := TRUE END;
  521.  
  522.     (* None of the above -> Msg by TIMER, mouseButtons *)
  523.     DLd.CheckDrives(FALSE);
  524.  
  525.   END; (* WHILE *)
  526.  
  527.   IF (~ quickquit) AND DLd.OneLocked() THEN
  528.     count := SHORT(DLr.RequestResponseNum(
  529.                 sys.ADR("DeviceLock"),
  530.                 DLs.GetString(DLs.MsgKeepUnlock),
  531.                 DLs.GetString(DLs.GadKeepUnlock),
  532.                 NIL));
  533.     IF (count = 0) THEN
  534.        terminated := FALSE;
  535.     ELSIF (count = 1) THEN   
  536.        DLd.UnlockAll(TRUE);
  537.     END;
  538.   END;
  539.  
  540. END; (* WHILE *)
  541.  
  542. (***************************************************************************
  543.          C L O S E
  544.  ***************************************************************************)
  545.  
  546. CLOSE
  547.   IF (I.int.libNode.version>=37) THEN
  548.     IF windowopen THEN
  549.       CloseWindow
  550.     ELSIF (TimeReq # NIL) THEN
  551.       IF e.CheckIO(TimeReq)= NIL THEN e.AbortIO(TimeReq) END;
  552.       IF e.WaitIO(TimeReq) = 0   THEN END;
  553.     END;
  554.     IF (quickquit AND (~ keepquit)) OR (ol.Result > 0) THEN
  555.       IF DLp.drive # NIL THEN DLd.UnlockAll(TRUE); END
  556.     END;
  557.     IF OpenDev = 0             THEN e.CloseDevice(TimeReq)        END;
  558.     (* Save to call with NIL ! *)   e.DeleteIORequest(TimeReq);
  559.     (* Save to call with NIL ! *)   e.DeleteMsgPort(TimerPort);
  560.   END;
  561.   IF (ol.Result > 0) THEN I.DisplayBeep(NIL) END;
  562.  
  563. END DeviceLock.
  564.